package utils

import (
	"fmt"
	"net"
	"strconv"
	"strings"
)

func IsIPAddr(ip string) (string, int, bool) {
	ip = strings.TrimSpace(ip)
	ip = strings.ToUpper(ip)
	ipAddr := net.ParseIP(ip)
	if ipAddr == nil {
		return "", 0, false
	}

	if strings.Contains(ip, ".") {
		return ip, 4, true
	}
	return ip, 6, true
}

func IsIPMask(mask string) (string, int, bool) {
	var maskType int
	maskNum := GetMaskNum(mask)
	maskStr := "0x" + maskNum

	if len(maskNum) == 8 {
		maskType = 4
	} else if len(maskNum) == 32 {
		maskType = 6
	} else {
		return "", maskType, false
	}
	return maskStr, maskType, isIPMask(maskNum)
}

func isIPMask(mask string) bool {
	var preZero bool
	for i := 0; i < len(mask); i += 4 {
		zeroAll, zero, ok := IsMask(mask[i : i+4])
		if !ok {
			return false
		}
		if preZero && !zeroAll {
			return false
		}
		preZero = zero
	}
	return true
}

func IsPortMask(mask string) (string, bool) {
	maskNum := GetMaskNum(mask)
	maskStr := "0x" + maskNum
	if len(maskNum) != 4 {
		return "", false
	}
	_, _, ok := IsMask(maskNum)
	return maskStr, ok
}

func GetMaskNum(mask string) string {
	mask = strings.TrimSpace(mask)
	mask = strings.ToUpper(mask)
	if !strings.HasPrefix(mask, "0X") {
		return ""
	}
	maskNum := mask[2:]
	if strings.HasPrefix(maskNum, "0") || strings.HasSuffix(maskNum, "F") {
		return ""
	}
	return maskNum
}

func IsMask(mask string) (zeroAll, zero, ret bool) {
	zeroAll = true
	num, err := strconv.ParseUint(mask, 16, 16)
	if err != nil {
		return
	}

	binStr := fmt.Sprintf("%b", num)
	if len(binStr) < 16 {
		zero = true
	}
	for _, c := range binStr {
		if zero && c == '1' {
			zeroAll = false
			return
		}
		if c == '0' {
			zero = true
		} else {
			zeroAll = false
		}
	}
	ret = true
	return
}

func IsPort(port int) bool {
	if port < 0 || port > 65535 {
		return false
	}
	return true
}
